package com.jun.admin.core.service.impl;

import cn.hutool.core.util.IdUtil;
import com.google.common.collect.Lists;
import com.jun.admin.core.mapper.JunStudentMapper;
import com.jun.admin.core.mapper.JunTeacherMapper;
import com.jun.admin.core.model.JunStudent;
import com.jun.admin.core.model.JunTeacher;
import com.jun.admin.core.model.User;
import com.jun.admin.core.model.strategy.PaymentStrategy;
import com.jun.admin.core.model.strategy.PaymentStrategyFactory;
import com.jun.admin.core.service.IndexService;
import com.jun.common.core.exception.ServiceException;
import com.jun.common.redis.aspect.anno.RedisLock;
import com.jun.common.redis.utils.RedisLockUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author yuejun.li
 * @date 2024/6/13 11:16:56
 */
@Service
@Slf4j
@AllArgsConstructor
public class IndexServiceImpl implements IndexService {

    private JunStudentMapper junStudentMapper;
    private JunTeacherMapper junTeacherMapper;
    private ApplicationContext applicationContext;
    private PaymentStrategyFactory strategyFactory;
    private RedissonClient redissonClient;
    private RedisLockUtil redisLockUtil;
    private RedisTemplate redisTemplate;

    @Override
    @Transactional
    public boolean transactional() {
        IndexServiceImpl indexService = applicationContext.getBean(IndexServiceImpl.class);
        JunTeacher junTeacher = new JunTeacher();
        junTeacher.setTeacherName("主方法测试");
        junTeacher.setAge(25);
        //模拟失败的情况
        junTeacherMapper.insertSelective(junTeacher);
        indexService.studentDeal();
        //indexService.teacherDeal();
        return true;
    }

    @Override
    public boolean strategy() {
        //数据库查到的枚举或者是前端传来的枚举
        PaymentStrategy paymentStrategy = strategyFactory.doOperate("commonPaymentStrategy");
        paymentStrategy.paymentStyle();
        return true;
    }

    @Override
    public List<JunStudent> desensitization() {
        return junStudentMapper.selectAll();
    }

    @Override
    public boolean thread() throws Throwable {
        IndexServiceImpl indexService = applicationContext.getBean(IndexServiceImpl.class);
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        //获取Spring自带的DataSourceTransactionManager对象
        DataSourceTransactionManager transactionManager = applicationContext.getBean(DataSourceTransactionManager.class);
        //创建默认的TransactionDefinition对象
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        //设置事务传播
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        //开启事务/获取事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);

        JunTeacher junTeacher = new JunTeacher();
        junTeacher.setTeacherName("主方法测试");
        junTeacher.setAge(25);
        junTeacherMapper.insertSelective(junTeacher);

        List<Future> futures = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            futures.add(executorService.submit(() -> {
                TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
                transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                transactionTemplate.execute(status -> {
                    // 在事务中执行操作
                    indexService.teacherDeal(finalI);
                    status.setRollbackOnly();
                    return null;
                });
            }));
        }

        for (Future future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                //手动回滚
                transactionManager.rollback(transactionStatus);
                log.error("多线程异常：{}",e.getMessage());
                throw e;
            }
        }

        //手动提交
        transactionManager.commit(transactionStatus);
        return true;
    }

    @Override
    public Object update(String id) {

        return null;
    }

    @RedisLock("com.jun.admin.core.service.impl.IndexServiceImpl.lockBean")
    @Override
    public Boolean lockBean(@RedisLock.KeyParamBean User user) throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        return null;
    }

    @Override
    public void redis() {
        /*Object key2 = redisTemplate.opsForValue().get("name1");
        System.out.println(key2);*/
        //redisTemplate.opsForValue().setIfAbsent("name2","hello");

    }

    @Override
    @Transactional
    public void completableFuture() throws ExecutionException, InterruptedException {

    }

    @RedisLock(value = "com.jun.admin.core.service.impl.IndexServiceImpl.lock")
    @Override
    public boolean lock(@RedisLock.KeyParam(1) String id, @RedisLock.KeyParam(2) Integer age) throws InterruptedException {
        System.out.println("获取锁成功，我在工作");
        TimeUnit.SECONDS.sleep(10);
        return true;
    }


    /*@Override
    public boolean thread() throws Throwable {
        IndexServiceImpl indexService = applicationContext.getBean(IndexServiceImpl.class);
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        List<Callable<Boolean>> futures = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            futures.add(() -> {
                indexService.studentDeal();
                throw new ServiceException("我抛的异常");
            });
        }

        List<Future<Boolean>> futures1 = executorService.invokeAll(futures);
        for (Future<Boolean> booleanFuture : futures1) {

            try {
                booleanFuture.get();
            } catch (ExecutionException e) {
                throw e.getCause();
            }
        }
        return true;
    }*/

    @Transactional
    @Async
    public void studentDeal() {
        JunStudent junStudent = new JunStudent();
        junStudent.setStudentName("李岳俊");
        junStudent.setAge(25);
        junStudentMapper.insertSelective(junStudent);
    }

    @Transactional
    public void teacherDeal(int i) {
        JunTeacher junTeacher = new JunTeacher();
        junTeacher.setTeacherName("庄松欣"+i);
        junTeacher.setAge(25);
        //模拟失败的情况
        junTeacherMapper.insertSelective(junTeacher);
        if(i == 3){
            throw new ServiceException("我抛的异常");
        }
    }


    public JunTeacher getJunTeacher(){
        JunTeacher junTeacher = new JunTeacher();
        junTeacher.setTeacherName("庄松欣"+ IdUtil.simpleUUID());
        junTeacher.setAge(25);
        System.out.println("教师填充完毕");
        return junTeacher;
    }

    public JunStudent getJunStudent(){
        JunStudent junStudent = new JunStudent();
        junStudent.setStudentName("庄松欣"+ IdUtil.simpleUUID());
        junStudent.setAge(25);
        System.out.println("学生填充完毕");
        return junStudent;
    }
}
